package cn.lili.modules.promotion.serviceimpl;

import cn.lili.cache.LockPrefix;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.promotion.entity.dos.BlindboxCount;
import cn.lili.modules.promotion.entity.dos.BlindboxCountInfo;
import cn.lili.modules.promotion.entity.dos.BlindboxPrizePaper;
import cn.lili.modules.promotion.entity.dos.BlindboxRule;
import cn.lili.modules.promotion.entity.dto.CallbackBlindboxDTO;
import cn.lili.modules.promotion.manage.BlindboxCountManage;
import cn.lili.modules.promotion.mapper.BlindboxCountMapper;
import cn.lili.modules.promotion.service.BlindboxCountInfoService;
import cn.lili.modules.promotion.service.BlindboxCountService;
import cn.lili.modules.promotion.service.BlindboxPrizeRecordService;
import cn.lili.modules.promotion.service.BlindboxRuleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * 盲盒统计 业务实现
 *
 * @author xiangqian
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class BlindboxCountServiceImpl extends ServiceImpl<BlindboxCountMapper, BlindboxCount> implements BlindboxCountService {

    @Resource
    private BlindboxCountInfoService blindboxCountInfoService;
    @Resource
    private BlindboxRuleService blindboxRuleService;
    @Resource
    private BlindboxCountManage blindboxCountManage;
    @Resource
    private BlindboxPrizeRecordService blindboxPrizeRecordService;
    @Resource
    private RedissonClient redisson;

    /**
     * 根据商品ID查询盲盒统计信息
     *
     * @param goodsId 商品ID
     * @return 盲盒统计
     */
    @Override
    public List<BlindboxCount> getBlindboxCountByGoodsId(String goodsId) {
        if (StringUtils.isNotEmpty(goodsId)) {
            return null;
        }

        QueryWrapper<BlindboxCount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_id", goodsId);
        queryWrapper.eq("delete_flag", false);
        List<BlindboxCount> list = this.baseMapper.selectList(queryWrapper);
        return list;
    }

    /**
     * 下单后更新盲盒统计
     *
     * @param callbackBlindboxDTO 订单信息
     */
    @Override
    @Transactional
    @ShardingTransactionType(TransactionType.BASE)
    public Boolean callbackBlindbox(CallbackBlindboxDTO callbackBlindboxDTO) {
        RLock lock = null;
        //锁下单后更新盲盒统计
        try {
            lock = redisson.getLock(LockPrefix.CALLBACK_BLINDBOX.getPrefix() + callbackBlindboxDTO.getGoodsId());
            lock.lock(100, TimeUnit.SECONDS);
            log.info("1.进入盲盒流程");
            //查询盲盒规则
            BlindboxRule blindboxRule = blindboxRuleService.getBlindboxRule(callbackBlindboxDTO.getGoodsId());
            if(blindboxRule == null){
                return false;
            }
            //查询购买数量是否超过盲盒库存
            LambdaQueryWrapper<BlindboxCount> lambdaQueryWrapper = new LambdaQueryWrapper();
            lambdaQueryWrapper.eq(BlindboxCount::getGoodsId, callbackBlindboxDTO.getGoodsId());
            List<BlindboxCount> blindboxCountList = this.baseMapper.selectList(lambdaQueryWrapper);
            Integer sumNumber = Optional.ofNullable(blindboxCountList).orElse(new ArrayList<>()).stream().mapToInt(BlindboxCount::getBuyNum).sum();
            if(sumNumber + callbackBlindboxDTO.getOrderNumber() > blindboxRule.getRuleNum() * blindboxRule.getRuleBuyNum()){
                return false;
            }
            //查询盲盒订单号是否存在
            LambdaQueryWrapper<BlindboxCountInfo> lambdaQueryWrapperCountInfo = new LambdaQueryWrapper();
            lambdaQueryWrapperCountInfo.eq(BlindboxCountInfo::getOrderId,callbackBlindboxDTO.getOrderId());
            List<BlindboxCountInfo> blindboxCountInfos = blindboxCountInfoService.getBaseMapper().selectList(lambdaQueryWrapperCountInfo);
            if(blindboxCountInfos!=null&&blindboxCountInfos.size()>0){
                return false;
            }


            //更新盲盒统计
            BlindboxCount blindboxCount = updateBlindboxCount(callbackBlindboxDTO.getUserId(), callbackBlindboxDTO.getGoodsId(), callbackBlindboxDTO.getOrderNumber());
            //盲盒统计详情
            blindboxCountInfoService.addBlindboxCountInfo(callbackBlindboxDTO.getUserId(), blindboxCount.getId(), callbackBlindboxDTO.getOrderId(), callbackBlindboxDTO.getOrderNumber());
            //分配奖卷
            blindboxCountManage.dominatePaer(callbackBlindboxDTO.getUserId(), callbackBlindboxDTO.getGoodsId(), blindboxRule, callbackBlindboxDTO.getOrderNumber());
            //查询所有商品所有奖卷
            List<BlindboxPrizePaper> blindboxPrizePaperList = blindboxCountManage.getBlindboxPrizePaper(callbackBlindboxDTO.getGoodsId());
            //新增盲盒奖品与订单关联关系
            blindboxCountManage.blindboxRuleOrder(callbackBlindboxDTO,blindboxRule);

            //是否达到开奖条件
            Boolean flag = blindboxCountManage.checkPrizeCondition(blindboxRule, blindboxPrizePaperList.size());
            log.info("flag---" + flag);
            log.info("blindboxPrizePaperList.size()---" + blindboxPrizePaperList.size());
            log.info("blindboxRule.getRuleNum()---" + blindboxRule.getRuleNum());
            if(flag){
                //生成开奖奖卷
                String code = blindboxCountManage.generatePrize(blindboxPrizePaperList);
                //生成开奖记录
                blindboxPrizeRecordService.insertBlindboxPrizeRecord(callbackBlindboxDTO,blindboxRule,code);
            }
        } catch (ServiceException e) {
            throw e;
        } finally {
            if (lock != null) {
                lock.unlock();
                log.info("强制释放锁");
            }
        }

        log.info("2.流程执行完毕");
        return true;
    }

    /**
     * 更新统计信息
     *
     * @param userId      用户ID
     * @param goodsId     商品ID
     * @param orderNumber 购买数量
     */
    @Override
    public BlindboxCount updateBlindboxCount(String userId, String goodsId, Integer orderNumber) {
        //检索统计信息是否存在
        LambdaQueryWrapper<BlindboxCount> lambdaQueryWrapper = new LambdaQueryWrapper();
        lambdaQueryWrapper.eq(BlindboxCount::getUserId, userId);
        lambdaQueryWrapper.eq(BlindboxCount::getGoodsId, goodsId);
        lambdaQueryWrapper.last("limit 1");
        BlindboxCount blindboxCount = this.baseMapper.selectOne(lambdaQueryWrapper);

        //处理统计信息
        if (blindboxCount == null) {
            //统计信息不存在
            BlindboxCount item = new BlindboxCount();
            item.setUserId(userId);
            item.setGoodsId(goodsId);
            item.setBuyNum(orderNumber);
            this.baseMapper.insert(item);
            blindboxCount = item;
        } else {
            //统计信息存在
            blindboxCount.setBuyNum(blindboxCount.getBuyNum() + orderNumber);
            this.baseMapper.updateById(blindboxCount);
        }
        return blindboxCount;
    }

}